/*
 * Copyright 2010 Marcin Blazejewski
 *
 * This file is part of Nofate.
 *
 * Nofate is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Nofate is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Nofate. If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "dialog.hpp"
#include <redeye.h>
#include <abstract/map.hpp>
#include <string>

Dialog::Dialog() {
    parent = NULL;
    ret_code = DRC_NONE;
    ret_selected = -1;
    focus = 0;
}

Dialog::~Dialog() {
}

void Dialog::draw() {
    vector<ListItem>::iterator i;
    int j;
    int cy = 2;
    int cx = 5;
    string txt;
    int fg = 0xE0E0E0;
    int bg = 0x0;

    // refresh focus by moving forwards and backwards once
    // the model might have changed since the last draw() call
    focus_next(-1);
    focus_next(1);

    // draw all items
    for (j=0, i = items.begin(); i != items.end(); i++, j++) {
        txt = "";

        // assing key to focusable items
        if (i->flags & DF_FOCUSABLE) {
            re_puts(cx, cy, 0xE0E0E0, 0x0, "[ ] ");
            cx += 4;
        }

        if (j == focus) txt += "> ";
        else txt += "  ";

        // set colors and text 
        if (i->flags & DF_SUBITEM) {
            txt += "[ ";
            txt += i->txt;
            txt += " ]";

            if (j == focus) fg = 0xF03030;
            else fg = 0x7030A0;
        } else {
            txt += i->txt;
            if (j == focus) fg = 0x30F0F0;
            else fg = 909090;
        }
        
        // draw
        re_puts(cx, cy, fg, bg, txt.c_str());
        cy++;
        cx = 5;
    }
}

void Dialog::focus_next(char inc) {
    if (focus < 0) return;    

    int i = focus;         // items iterator
    int c = 0;             // focus shift attempts counter
    
    // assume we fail to find any focusable object 
    // (first time this is called we don't know if there is any)
    focus = -1;
        
    // try iterating forward or backward through all items
    // until focusable is found, or all items have been tried
    while (c < items.size()) {
        // try next item (with wrap around)
        i += inc;
        if (i >= items.size()) i = 0;
        else if (i < 0) i = items.size() - 1;
        c++;

        if (items[i].flags & DF_FOCUSABLE) {
            // found focusable
            focus = i;
            break;
        }
    }

}

Action* Dialog::process_input(AreaMap *area) {
    SDL_Event e;
    Action *a = NULL;

    while (a == NULL) {
        /* error */
        if (SDL_WaitEvent(&e) == 0) {
            return NULL;
        }
        /* quit */
        else if (e.type == SDL_QUIT) {
            return NULL;
        }
        /* keyboard */
        else if (e.type == SDL_KEYUP) {
            char ctrl = e.key.keysym.mod & KMOD_CTRL;
            char shift = e.key.keysym.mod & KMOD_SHIFT;
            
            if (!shift && !ctrl) {
                switch (e.key.keysym.sym) {
                case SDLK_q:     ret_code = DRC_BACK; return NULL;
                case SDLK_UP:    focus_next (1); return NULL;
                case SDLK_DOWN:  focus_next(-1); return NULL;
                default: break;
                }
            }
            break;
        } /* keyup */
    } /* while a==NULL */

    return a;
}
